package com.alibaba.citrus.cr.mn.order.center.forecastorder.service.impl;

import cn.hutool.core.date.StopWatch;
import com.alibaba.citrus.cr.common.constant.OrderFeaturesKey;
import com.alibaba.citrus.cr.common.enums.ordercenter.DictionaryTypeEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.ForecastOrderTypeEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.OrderChannelEnum;
import com.alibaba.citrus.cr.common.exception.FunctionException;
import com.alibaba.citrus.cr.common.util.DateUtils;
import com.alibaba.citrus.cr.mn.order.center.common.constants.ForecastConstants;
import com.alibaba.citrus.cr.mn.order.center.common.util.MoneyUtils;
import com.alibaba.citrus.cr.mn.order.center.common.util.StopWatchUtils;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.BaseDataServiceAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.repository.DealLineQueryRepository;
import com.alibaba.citrus.cr.mn.order.center.facade.repository.ForecastOrderLineQueryRepository;
import com.alibaba.citrus.cr.mn.order.center.facade.repository.ForecastOrderQueryRepository;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.convert.ForecastOrderSDOToResponseConvertor;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.service.ForecastOrderBizQueryService;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.forecast_sales.ForecastOrderTag;
import com.epoch.app.bcorder.platform_enhance.SaleOrderTag;
import com.epoch.app.crforecastsales.domian.forecastorder.dto.LoadMainOrderByBizIdRequest;
import com.epoch.app.crforecastsales.domian.forecastorder.model.ForecastOrder;
import com.epoch.app.crforecastsales.domian.forecastorder.service.ForecastOrderService;
import com.epoch.app.crforecastsales.domian.forecastorderline.dto.GetOrderLineByMainOrderIdRequest;
import com.epoch.app.crforecastsales.domian.forecastorderline.model.ForecastOrderLine;
import com.epoch.app.crforecastsales.domian.forecastorderline.service.ForecastOrderLineService;
import com.epoch.app.crforecastsales.enums.ForecastStatusEnum;
import com.epoch.app.crforecastsales.forecastorderlineindex.model.ForecastOrderLineIndex;
import com.epoch.app.crforecastsales.forecastorderlineindex.service.ForecastOrderLineIndexService;
import com.epoch.app.crforecastsales.model.dto.ActivityDTO;
import com.epoch.app.crforecastsales.model.dto.ActivitySDO;
import com.epoch.app.crforecastsales.model.dto.SearchForecastOrderRequest;
import com.epoch.app.crforecastsales.sdo.ForecastOrderLineSDO;
import com.epoch.app.crforecastsales.sdo.ForecastOrderSDO;
import com.epoch.app.mnordercenter.model.dto.*;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.alibaba.citrus.cr.common.util.DateUtils.*;

@Service
@Primary
public class ForecastOrderBizQueryServiceImpl implements ForecastOrderBizQueryService {
    private static final Log log = Log.getLogger(ForecastOrderBizQueryServiceImpl.class);

    @Resource
    ForecastOrderLineIndexService forecastOrderLineIndexService;
    @Resource
    ForecastOrderService forecastOrderService;
    @Resource
    ForecastOrderLineService forecastOrderLineService;
    @Resource
    private DealLineQueryRepository dealLineQueryRepository;
    @Resource(name = "forecastOrderQueryRepositoryBiz")
    private ForecastOrderQueryRepository forecastOrderQueryRepository;
    @Resource(name = "forecastOrderLineQueryRepositoryBiz")
    private ForecastOrderLineQueryRepository forecastOrderLineQueryRepository;
    @Resource
    private BaseDataServiceAdapter baseDataServiceAdapter;

    @Override
    public QueryForecastResponse query(QueryForecastRequest request) {
        log.info("ForecastOrderBizQueryServiceImpl#query request={}", request);
        StopWatch stopWatch = new StopWatch("ForecastOrderBizQueryServiceImpl#query");

        stopWatch.start("loadMainOrderByBizId");
        LoadMainOrderByBizIdRequest loadMainOrderByBizIdRequest = new LoadMainOrderByBizIdRequest();
        loadMainOrderByBizIdRequest.setOrderBizId(request.getSalesOrderNo());
        loadMainOrderByBizIdRequest.setSourceOrderNo(request.getSourceOrderNo());
        loadMainOrderByBizIdRequest.setFromSys(request.getFromSys());
        loadMainOrderByBizIdRequest.setBusinessType(request.getBusinessType());
        loadMainOrderByBizIdRequest.setBusinessUnitCode(request.getBusinessUnitCode());
        loadMainOrderByBizIdRequest.setOrderCategoryCode(request.getOrderCategoryCode());
        Result<ForecastOrder> result = forecastOrderService.loadMainOrderByBizId(loadMainOrderByBizIdRequest);
        stopWatch.stop();

        if (result.getResult() != null) {
            ForecastOrder source = result.getResult();
            stopWatch.start("getOrderLineByMainOrderId");
            GetOrderLineByMainOrderIdRequest getOrderLineByMainOrderIdRequest = new GetOrderLineByMainOrderIdRequest();
            getOrderLineByMainOrderIdRequest.setLimit(100);
            getOrderLineByMainOrderIdRequest.setStart(0);
            getOrderLineByMainOrderIdRequest.setIds(Collections.singletonList(String.valueOf(source.getId())));
            Result<List<ForecastOrderLine>> lineResult = forecastOrderLineService.getOrderLineByMainOrderId(getOrderLineByMainOrderIdRequest);
            stopWatch.stop();

            List<QueryForecastDetailResponseDTO> detailList = new ArrayList<>();
            stopWatch.start("forecastOrderLine2QueryForecastDetailResponseDTO");
            if (CollectionUtils.isNotEmpty(lineResult.getResult())) {
                lineResult.getResult().forEach(x -> detailList.add(forecastOrderLine2QueryForecastDetailResponseDTO(x)));
            }
            stopWatch.stop();

            stopWatch.start("forecastOrder2QueryQueryForecastResponse");
            QueryForecastResponse target = forecastOrder2QueryQueryForecastResponse(source);
            target.setForecastDetailDTOS(detailList);
            stopWatch.stop();

            log.info("ForecastOrderBizQueryServiceImpl#query stopWatch.getTotalTimeSeconds()={}", stopWatch.getTotalTimeSeconds());
            log.info("ForecastOrderBizQueryServiceImpl#query stopWatch.prettyPrint()={}", stopWatch.prettyPrint());
            return target;
        }
        return null;
    }

    @Override
    public Result<List<ForecastOrderBizQueryActivityResponse>> batchQueryActivity(ForecastOrderBizBatchQueryActivityRequest request) {
        List<String> salesOrderNos = request.getOrderList().stream()
                .map(ForecastOrderBizQueryActivityRequest::getSalesOrderNo)
                .collect(Collectors.toList());

        // 根据预报订单号查询预报订单
        StopWatchUtils.start("预报订单批量查询活动", "queryByOrderBizNo");
        List<ForecastOrderSDO> forecastOrderSDOS = forecastOrderQueryRepository.queryByOrderBizNo(salesOrderNos);
        StopWatchUtils.stop();
        if (CollectionUtils.isEmpty(forecastOrderSDOS)) {
            return Result.success(Lists.newArrayList());
        }

        StopWatchUtils.start("预报订单批量查询活动", "buildResponses");
        List<ForecastOrderBizQueryActivityResponse> responses = new ArrayList<>();
        // 根据主单ID进行分组
        for (ForecastOrderSDO forecastOrderSDO : forecastOrderSDOS) {
            // 查询命中活动详情
            List<ActivitySDO> activitySDOS = this.queryActivity(forecastOrderSDO);
            if (CollectionUtils.isEmpty(activitySDOS)) {
                continue;
            }

            //按业态单元编码过滤
            if (StringUtils.isNotBlank(request.getBusinessUnitCode())) {
                if (!request.getBusinessUnitCode().equals(forecastOrderSDO.getBusinessUnitCode())) {
                    continue;
                }
            }

            Map<String, List<ActivitySDO>> activitySDOMap = activitySDOS.stream().collect(Collectors.groupingBy(ActivitySDO::getSubOrderId));
            log.info("ForecastOrderBizQueryServiceImpl#batchQueryActivity activitySDOMap={}", activitySDOMap);
            Map<String, ForecastOrderLineSDO> forecastOrderLineSDOMap = forecastOrderSDO.getForecastOrderLineSDOList()
                    .stream().collect(Collectors.toMap(forecastOrderLineSDO -> forecastOrderLineSDO.getId().toString(), Function.identity(), (v1, v2) -> v1));
            log.info("ForecastOrderBizQueryServiceImpl#batchQueryActivity forecastOrderLineSDOMap={}", forecastOrderLineSDOMap);

//            StopWatchUtils.start("预报订单批量查询活动", "queryForecastOrderLine");
            for (String subId : activitySDOMap.keySet()) {
//                ForecastOrderLineSDO forecastOrderLineSDO = forecastOrderLineQueryRepository.query(subId);
                ForecastOrderLineSDO forecastOrderLineSDO = forecastOrderLineSDOMap.get(subId);
                if (Objects.isNull(forecastOrderLineSDO)) {
                    continue;
                }
                List<ActivitySDO> lineActivitySDOS = activitySDOMap.get(subId);
                // 构造返回参数
                ForecastOrderBizQueryActivityResponse response = convertActivityResponse(forecastOrderSDO, forecastOrderLineSDO, lineActivitySDOS);
                responses.add(response);
            }
//            StopWatchUtils.stop();
        }
        StopWatchUtils.stop();

        return Result.listSuccess(responses, responses.size());
    }

    private List<ActivitySDO> queryActivity(ForecastOrderSDO forecastOrderSDO) {
        List<ActivitySDO> activitySDOSAll = new ArrayList<>();
        for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderSDO.getForecastOrderLineSDOList()) {
            List<ActivitySDO> activitySDOS = new ArrayList<>();
            Map<String, Object> features = forecastOrderLineSDO.getFeatures();
            //补货订单
            if (ForecastOrderTag.RESTOCK_FORECAST.getValue().equals(forecastOrderSDO.getOrderType())) {
                ActivitySDO activityNewSDO = new ActivitySDO();
                activityNewSDO.setActivityName(forecastOrderLineSDO.getActivityName());
                activityNewSDO.setActivityType("ZS42");
                //补货订单默认选中
                activityNewSDO.setIsSelect(true);
                activityNewSDO.setActivityCode(forecastOrderLineSDO.getActivityCode());
                activityNewSDO.setActivityTermid(features.get(ForecastConstants.ACTIVITY_NUMBER) == null ? "" : features.get(ForecastConstants.ACTIVITY_NUMBER).toString());
                activityNewSDO.setSubOrderId(String.valueOf(forecastOrderLineSDO.getId()));
                activityNewSDO.setActivitydeal(features.get(ForecastConstants.REPLENISHMENT_ACTIVITY_REMAINING_QUANTITY) == null ? 0 : Integer.parseInt(features.get(ForecastConstants.REPLENISHMENT_ACTIVITY_REMAINING_QUANTITY).toString()));
                activityNewSDO.setActivityfee(features.get(ForecastConstants.REPLENISHMENT_ACTIVITY_REMAINING_FEE) == null ? 0L : Long.parseLong(features.get(ForecastConstants.REPLENISHMENT_ACTIVITY_REMAINING_FEE).toString()));
                activityNewSDO.setIntensityOfActivityDesc(features.get(ForecastConstants.REPLENISHMENT_INTENSITY_OF_ACTIVITY_DESC) == null ? "" : String.valueOf(features.get(ForecastConstants.REPLENISHMENT_INTENSITY_OF_ACTIVITY_DESC)));
                activitySDOS.add(activityNewSDO);
            } else {
                activitySDOS = JSONObject.parseArray(JSON.toJSONString(features.get(ForecastConstants.ACTIVITY_DETAILS)), ActivitySDO.class);
                if (CollectionUtils.isNotEmpty(activitySDOS)) {
                    activitySDOS.forEach(sdo -> sdo.setSubOrderId(String.valueOf(forecastOrderLineSDO.getId())));
                    //各类型默认选中第一个活动
                }
            }
            activitySDOSAll.addAll(Optional.ofNullable(activitySDOS).orElse(Lists.newArrayList()));
        }
        return activitySDOSAll;
    }

    private ForecastOrderBizQueryActivityResponse convertActivityResponse(ForecastOrderSDO forecastOrderSDO, ForecastOrderLineSDO forecastOrderLineSDO, List<ActivitySDO> activitySDOS) {
        Map<String, List<ActivitySDO>> activityTypeMap = new HashMap<>();
        ForecastOrderBizQueryActivityResponse response = new ForecastOrderBizQueryActivityResponse();
        if (CollectionUtils.isNotEmpty(activitySDOS)) {
            Nullable.stream(activitySDOS).forEach(o -> o.setUnitPrice(forecastOrderLineSDO.getUnitPrice()));
            activityTypeMap = Nullable.stream(activitySDOS).collect(Collectors.groupingBy(ActivitySDO::getActivityType));
        }
        List<ActivitySDO> activityChooseList;
        Map<String, Object> features = forecastOrderLineSDO.getFeatures();
        String activityTag = MapUtils.isNotEmpty(features) ? String.valueOf(features.getOrDefault(ForecastConstants.ACTIVITY_TAG, "0")) : "0";
        if (MapUtils.isNotEmpty(activityTypeMap)) {
            activityChooseList = activityTypeMap.get("ZS42");
            if (CollectionUtils.isEmpty(activityChooseList)) {
                if (CollectionUtils.isNotEmpty(activityTypeMap.get("ZS02"))) {
                    List<ActivitySDO> giftActivitySDOList = activityTypeMap.get("ZS02");
                    boolean haveSelectedActivity = giftActivitySDOList.stream().anyMatch(ActivitySDO::getIsSelect);
                    ActivityDTO activityDTO = new ActivityDTO();
                    activityDTO.setList(giftActivitySDOList);
                    activityDTO.setEnabled(haveSelectedActivity);
                    activityDTO.setActivityType("ZS02");
                    if (haveSelectedActivity) {
                        ActivitySDO selectActivitySDO = giftActivitySDOList.stream().filter(ActivitySDO::getIsSelect).findAny().orElse(new ActivitySDO());
                        activityDTO.setSelectedActivityCode(selectActivitySDO.getActivityCode());
                    }
                    response.setGiftActivity(JSON.toJSONString(activityDTO));
                    //默认选中第一个(分析完成以后，初次查询活动)
                    if (activityTag.equals("1")) {
                        ActivitySDO defaultSelectActivity = giftActivitySDOList.get(0);
                        activityDTO.setEnabled(Boolean.TRUE);
                        activityDTO.setSelectedActivityCode(defaultSelectActivity.getActivityCode());
                    }
                }
            } else {
                boolean haveSelectedActivity = activityChooseList.stream().anyMatch(ActivitySDO::getIsSelect);
                ActivityDTO activityDTO = new ActivityDTO();
                activityDTO.setList(activityChooseList);
                activityDTO.setEnabled(haveSelectedActivity);
                activityDTO.setActivityType("ZS42");
                if (haveSelectedActivity) {
                    ActivitySDO selectActivitySDO = activityChooseList.stream().filter(ActivitySDO::getIsSelect).findAny().orElse(new ActivitySDO());
                    activityDTO.setSelectedActivityCode(selectActivitySDO.getActivityCode());
                }
                response.setGiftActivity(JSON.toJSONString(activityDTO));
            }

            if (CollectionUtils.isNotEmpty(activityTypeMap.get("ZS03"))) {
                List<ActivitySDO> giftActivitySDOList = activityTypeMap.get("ZS03");
                boolean haveSelectedActivity = giftActivitySDOList.stream().anyMatch(ActivitySDO::getIsSelect);
                ActivityDTO activityDTO = new ActivityDTO();
                activityDTO.setList(giftActivitySDOList);
                activityDTO.setEnabled(haveSelectedActivity);
                activityDTO.setActivityType("ZS03");
                if (haveSelectedActivity) {
                    ActivitySDO selectActivitySDO = giftActivitySDOList.stream().filter(ActivitySDO::getIsSelect).findAny().orElse(new ActivitySDO());
                    activityDTO.setSelectedActivityCode(selectActivitySDO.getActivityCode());
                }
                response.setSpecialActivity(JSON.toJSONString(activityDTO));
                //默认选中第一个(分析完成以后，初次查询活动)
                if (activityTag.equals("1")) {
                    ActivitySDO defaultSelectActivity = giftActivitySDOList.get(0);
                    activityDTO.setEnabled(Boolean.TRUE);
                    activityDTO.setSelectedActivityCode(defaultSelectActivity.getActivityCode());
                }
            }

            // 设置预报业务id
            response.setSalesOrderNo(forecastOrderSDO.getOrderBizId());
            // 货品名称
            response.setProductName(forecastOrderLineSDO.getScItemTitle());
            // 行号
            response.setLineNum(String.valueOf(forecastOrderLineSDO.getSerialNumber()));
            // 客户名称
            response.setCustomerName(forecastOrderSDO.getCustomerName());
            // 预计回复数量
            response.setPredictReplyAmount(forecastOrderLineSDO.getPredictReplyAmount());
            // 明细备注
            response.setDetailRemark(forecastOrderLineSDO.getDetailRemark());
        }
        return response;
    }

    @Override
    public Result<List<PageQueryForecastDetailResponse>> pageQueryLine(PageQueryForecastLineRequest request, String orderCategory) {
        log.info("ForecastOrderBizQueryServiceImpl#pageQueryLine request={}", request);
        SearchForecastOrderRequest searchForecastOrderRequest = new SearchForecastOrderRequest();
        searchForecastOrderRequest.setFromSys(request.getFromSys());
        searchForecastOrderRequest.setOrderCategoryCode(orderCategory);
        searchForecastOrderRequest.setBusinessUnitCode(request.getBusinessUnitCode());
        searchForecastOrderRequest.setBusinessType(request.getBusinessType());
        searchForecastOrderRequest.setSourceOrderNoList(request.getSourceOrderNoList()); // 来源单号
        searchForecastOrderRequest.setForecastOrderBizNoList(request.getSalesOrderNoList()); // 预报订单号
        searchForecastOrderRequest.setOrderTypeCodeList(request.getOrderTypeCodeList());
        searchForecastOrderRequest.setShippingWarehouseCodeList(request.getShippingWarehouseCodeList()); // 发货逻辑仓库编码
        searchForecastOrderRequest.setOutIds(request.getProductCodeList()); // 物料编码数组
        searchForecastOrderRequest.setDeliveryFactoryCode(request.getDeliveryFactoryCode()); // 交货工厂编码
        searchForecastOrderRequest.setStockCode(request.getStockCode()); // 库存地点编码
        searchForecastOrderRequest.setCustomerExpectStartDate(DateUtils.formatString2Date(request.getExpectDeliveryBeginDate(), DATE_FORMAT));
        searchForecastOrderRequest.setCustomerExpectEndDate(DateUtils.formatString2Date(request.getExpectDeliveryEndDate(), DATE_FORMAT));
        if (CollectionUtils.isNotEmpty(request.getStatusList())) {
            try {
                searchForecastOrderRequest.setMainStatusList(request.getStatusList().stream().map(Integer::parseInt).collect(Collectors.toList()));
            } catch (Exception e) {
                throw new FunctionException("OC-00-001-01-15-001", "主单状态");
            }
        }
        if (CollectionUtils.isNotEmpty(request.getDetailStatusList())) {
            try {
                searchForecastOrderRequest.setDetailStatusList(request.getDetailStatusList().stream().map(Integer::parseInt).collect(Collectors.toList()));
            } catch (Exception e) {
                throw new FunctionException("OC-00-001-01-15-001", "明细状态");
            }
        }
        searchForecastOrderRequest.setGmtStartCreate(DateUtils.getBeginOrEndByStr(request.getCreateBeginTime(), true));
        searchForecastOrderRequest.setGmtEndCreate(DateUtils.getBeginOrEndByStr(request.getCreateEndTime(), false));
        searchForecastOrderRequest.setCustomerPurchaseOrderNoList(request.getCustomerPurchaseOrderNoList());
        searchForecastOrderRequest.setShipToPartyCodeList(request.getShipToPartyCodeList());
        searchForecastOrderRequest.setSoldToPartyCodeList(request.getCustomerCodeList());
        searchForecastOrderRequest.setPage(request.getPage() < 1 ? 1 : request.getPage());
        searchForecastOrderRequest.setSize(request.getSize());
        searchForecastOrderRequest.setLimit(request.getSize());
        searchForecastOrderRequest.setStart((searchForecastOrderRequest.getPage() - 1) * request.getSize());

        // 一盘货入参
        searchForecastOrderRequest.setFromSysList(request.getFromSysList());
        searchForecastOrderRequest.setBusinessUnitCodeList(request.getBusinessUnitCodeList());
        searchForecastOrderRequest.setOrderChannelCodeList(request.getOrderChannelCodeList());
//        searchForecastOrderRequest.setUpdateStartTime(DateUtils.formatString2Date(request.getModifyBeginTime(), DATETIME_FORMAT)); // 修改开始日期
//        searchForecastOrderRequest.setUpdateEndTime(DateUtils.formatString2Date(request.getModifyEndTime(), DATETIME_FORMAT)); // 修改结束日期
        searchForecastOrderRequest.setModifyBeginTime(DateUtils.convertToMillisecondStr(request.getModifyBeginTime()));
        searchForecastOrderRequest.setModifyEndTime(DateUtils.convertToMillisecondStr(request.getModifyEndTime()));
        searchForecastOrderRequest.setSaleChannelCodeList(request.getSalesChannelCodeList()); // 销售渠道编码
        searchForecastOrderRequest.setSalesDepartmentCodeList(request.getSalesDepartmentCodeList()); // 销售部门编码
        searchForecastOrderRequest.setValidStartDate(DateUtils.getFirstTime(request.getValidBeginDateStart())); // 生效开始日期（开始日期）
        searchForecastOrderRequest.setValidEndDate(DateUtils.getLastTime(request.getValidBeginDateEnd())); // 生效开始日期（结束日期）
        searchForecastOrderRequest.setSourceOrderStartDate(DateUtils.convertToMillisecondStr(request.getSourceOrderBeginTime()));
        searchForecastOrderRequest.setSourceOrderEndDate(DateUtils.convertToMillisecondStr(request.getSourceOrderEndTime()));
        searchForecastOrderRequest.setDeliveryMethodCode(request.getDeliveryMethodCode()); // 配送方式编码
        searchForecastOrderRequest.setFulfillmentTypeCode(request.getFulfillmentTypeCode()); // 履约方式
        searchForecastOrderRequest.setFulfillmentPriority(request.getFulfillmentPriority()); // 履约优先级
        searchForecastOrderRequest.setAutoFulfillment(request.getAutoFulfillment());
        searchForecastOrderRequest.setOrderTag(request.getOrderBizTag()); // 订单标签
        searchForecastOrderRequest.setRemark(request.getNote()); // 订单备注
        searchForecastOrderRequest.setCreatorCode(request.getCreatorCode()); // 创建人编码
        searchForecastOrderRequest.setModifierCode(request.getModifierCode()); // 修改人编码
        searchForecastOrderRequest.setOrderReasonCode(request.getOrderReasonCode()); // 订单原因编码
        searchForecastOrderRequest.setReceiveWarehouseCodeList(request.getReceiveWarehouseCodeList()); // 收货逻辑仓库编码
        if (StringUtils.isNotBlank(request.getLineNum())) {
            searchForecastOrderRequest.setLineNoList(Lists.newArrayList(request.getLineNum())); // 行号
        }
        searchForecastOrderRequest.setSourceLineNum(request.getSourceLineNum()); // 来源行号
        searchForecastOrderRequest.setProductQuantity(request.getProductQuantity()); // 预报数量
        searchForecastOrderRequest.setSaleUnitCode(request.getSaleUnitCode()); // 销售单位编码
        searchForecastOrderRequest.setInventoryUnitCode(request.getStockUnitCode()); // 库存单位编码
        searchForecastOrderRequest.setSubClosed(StringUtils.isBlank(request.getIsClose()) ? null : Long.parseLong(request.getIsClose())); // 是否关闭
        searchForecastOrderRequest.setRefuseReasonCodeList(request.getCloseReasonCodeList()); // 关闭原因编码
        searchForecastOrderRequest.setSubRemark(request.getDetailNote()); // 明细备注
        if (StringUtils.isNotBlank(request.getProductGroupCode())) {
            searchForecastOrderRequest.setProductGroupCodeList(Lists.newArrayList(request.getProductGroupCode()));
        }
        if (StringUtils.isNotBlank(request.getBusinessChannel())) {
            searchForecastOrderRequest.setChannelCodeList(Lists.newArrayList(request.getBusinessChannel()));
        }
        searchForecastOrderRequest.setSalesOrganizationCode(request.getSalesOrganizationCode());
        searchForecastOrderRequest.setCustomerGrade(request.getCustomerGrade());
        searchForecastOrderRequest.setCustomerGroup(request.getCustomerGroup());
        searchForecastOrderRequest.setDocReasonList(request.getOrderReasonCodeList());
        searchForecastOrderRequest.setContact(request.getContact());
        searchForecastOrderRequest.setContactPhone(request.getContactPhone());
        searchForecastOrderRequest.setReceiveStatusList(request.getReceiveStatusList());
        searchForecastOrderRequest.setDetailReceiveStatusList(request.getDetailReceiveStatusList());
        searchForecastOrderRequest.setDeliveryMethodCodeList(request.getDeliveryMethodCodeList());
        searchForecastOrderRequest.setKaSystemList(request.getKaSystemList());
        searchForecastOrderRequest.setKaAreaList(request.getKaAreaList());
        searchForecastOrderRequest.setOutOrderNoList(request.getOutOrderNoList());
        searchForecastOrderRequest.setAnalysisReasonCodeList(request.getAnalysisReasonList());
        searchForecastOrderRequest.setDeadlineStartDate(toMillisecondByTime(request.getDeadlineStartDate()));
        searchForecastOrderRequest.setDeadlineEndDate(toMillisecondByTime(request.getDeadlineEndDate()));
        if (CollectionUtils.isNotEmpty(request.getAnalysisStatusList())) {
            List<Integer> dealStatusList = request.getAnalysisStatusList().stream().map(Integer::parseInt).collect(Collectors.toList());
            searchForecastOrderRequest.setDealStatusList(dealStatusList);
        }

        Result<List<ForecastOrderLineIndex>> orderLineIndexResult = null;
        try {
            log.info("ForecastOrderBizQueryServiceImpl#pageQueryLine searchForecastOrderRequest={}", searchForecastOrderRequest);
            orderLineIndexResult = forecastOrderLineIndexService.queryForecastOrderLineByEs(searchForecastOrderRequest);
            log.info("ForecastOrderBizQueryServiceImpl#pageQueryLine orderLineIndexResult={}", orderLineIndexResult);
        } catch (Exception e) {
            log.error("ForecastOrderBizQueryServiceImpl#pageQueryLine error", e);
            throw new FunctionException("OC-01-001-01-16-057", "查询预报订单失败");
        }
        if (Objects.isNull(orderLineIndexResult) || CollectionUtils.isEmpty(orderLineIndexResult.getResult())) {
            return Result.success(Lists.newArrayList());
        }

        List<PageQueryForecastDetailResponse> finalList = orderLineIndexResult.getResult().stream()
                .map(this::forecastOrderLine2QueryQueryForecastResponse)
                .collect(Collectors.toList());
        return Result.listSuccess(finalList, orderLineIndexResult.getTotal());
    }

    @Override
    public Result<List<QueryForecastResponse>> pageQuery(PageQueryForecastRequest request, String orderCategory) {
        log.info("ForecastOrderBizQueryServiceImpl#pageQuery request={}", request);
        SearchForecastOrderRequest searchForecastOrderRequest = new SearchForecastOrderRequest();
        searchForecastOrderRequest.setForecastOrderBizNoList(request.getSalesOrderNoList());
        searchForecastOrderRequest.setOrderCategoryCode(orderCategory);
        searchForecastOrderRequest.setSourceOrderNoList(request.getSourceOrderNoList());
        searchForecastOrderRequest.setFromSys(request.getFromSys());
        searchForecastOrderRequest.setBusinessType(request.getBusinessType());
        searchForecastOrderRequest.setBusinessUnitCode(request.getBusinessUnitCode());
        searchForecastOrderRequest.setShippingWarehouseCodeList(request.getShippingWarehouseCodeList());
        searchForecastOrderRequest.setOrderTypeCodeList(request.getOrderTypeCodeList());
        searchForecastOrderRequest.setDeliveryFactoryCode(request.getDeliveryFactoryCode());
        searchForecastOrderRequest.setStockCode(request.getStockCode());
        searchForecastOrderRequest.setFromSysList(request.getFromSysList());
        searchForecastOrderRequest.setBusinessUnitCodeList(request.getBusinessUnitCodeList());
        searchForecastOrderRequest.setOrderChannelCodeList(request.getOrderChannelCodeList());
        searchForecastOrderRequest.setMainOrderBizId(request.getSalesOrderNo());
        searchForecastOrderRequest.setGmtStartCreate(DateUtils.string2Date(request.getCreateBeginTime()));
        searchForecastOrderRequest.setGmtEndCreate(DateUtils.string2Date(request.getCreateEndTime()));
//        searchForecastOrderRequest.setUpdateStartTime(DateUtils.convertToMillisecondStr(request.getModifyBeginTime()));
//        searchForecastOrderRequest.setUpdateEndTime(DateUtils.convertToMillisecondStr(request.getModifyEndTime()));
        searchForecastOrderRequest.setModifyBeginTime(DateUtils.convertToMillisecondStr(request.getModifyBeginTime()));
        searchForecastOrderRequest.setModifyEndTime(DateUtils.convertToMillisecondStr(request.getModifyEndTime()));
        searchForecastOrderRequest.setCustomerCode(request.getCustomerCode());
        searchForecastOrderRequest.setShipToPartyCode(request.getShipToPartyCode());
        searchForecastOrderRequest.setSalesOrganizationCode(request.getSalesOrganizationCode());
        searchForecastOrderRequest.setSalesDepartmentCode(request.getSalesDepartmentCode());
        if (CollectionUtils.isNotEmpty(request.getOrderStatusList())) {
            List<Integer> orderStatusList = request.getOrderStatusList().stream().map(status -> {
                return Integer.valueOf(status);
            }).collect(Collectors.toList());
            searchForecastOrderRequest.setMainStatusList(orderStatusList);
        }
        searchForecastOrderRequest.setValidStartDate(DateUtils.string2Date(request.getValidBeginDateStart()));
        searchForecastOrderRequest.setValidEndDate(DateUtils.string2Date(request.getValidBeginDateEnd()));
        searchForecastOrderRequest.setCustomerExpectStartDate(DateUtils.string2Date(request.getExpectedDeliveryBeginDate()));
        searchForecastOrderRequest.setCustomerExpectEndDate(DateUtils.string2Date(request.getExpectedDeliveryEndDate()));
        searchForecastOrderRequest.setDeliveryMethodCodeList(request.getDeliveryMethodCodeList());
        searchForecastOrderRequest.setRemark(request.getNote());
        searchForecastOrderRequest.setCreatorCode(request.getCreatorCode());
        searchForecastOrderRequest.setModifierCode(request.getModifierCode());
        searchForecastOrderRequest.setCustomerPurchaseOrderNo(request.getCustomerPurchaseOrderNo());
        searchForecastOrderRequest.setDocReasonList(request.getOrderReasonCodeList());
        searchForecastOrderRequest.setReceiveWarehouseCodeList(request.getReceiveWarehouseCodeList());
        searchForecastOrderRequest.setProductCodeList(request.getProductCodeList());
        searchForecastOrderRequest.setContact(request.getContact());
        searchForecastOrderRequest.setContactPhone(request.getContactPhone());
        searchForecastOrderRequest.setRefuseReasonCodeList(request.getCloseReasonCodeList());
        searchForecastOrderRequest.setFulfillmentTypeCode(request.getFulfillmentTypeCode());
        searchForecastOrderRequest.setFulfillmentPriority(request.getFulfillmentPriority());
        searchForecastOrderRequest.setOrderTag(request.getOrderBizTag());
        searchForecastOrderRequest.setCustomerGrade(request.getCustomerGrade());
        searchForecastOrderRequest.setCustomerGroup(request.getCustomerGroup());
        searchForecastOrderRequest.setSaleChannelCodeList(request.getSaleChannelCodeList());
        searchForecastOrderRequest.setPage(request.getPage() < 1 ? 1 : request.getPage());
        searchForecastOrderRequest.setSize(request.getSize());
        searchForecastOrderRequest.setLimit(request.getSize());
        searchForecastOrderRequest.setStart((searchForecastOrderRequest.getPage() - 1) * request.getSize());
        searchForecastOrderRequest.setOutIds(request.getOuterOrderNoList());
        if (StringUtils.isNotBlank(request.getBusinessChannel())) {
            searchForecastOrderRequest.setChannelCodeList(Lists.newArrayList(request.getBusinessChannel()));
        }
        if (StringUtils.isNotBlank(request.getProductGroupCode())) {
            searchForecastOrderRequest.setProductGroupCodeList(Lists.newArrayList(request.getProductGroupCode()));
        }
        searchForecastOrderRequest.setSaleChannelCodeList(request.getSalesChannelCodeList());
        searchForecastOrderRequest.setSalesDepartmentCodeList(request.getSalesDepartmentCodeList());
        searchForecastOrderRequest.setKaSystemList(request.getKaSystemList());
        searchForecastOrderRequest.setKaAreaList(request.getKaAreaList());
        searchForecastOrderRequest.setSourceOrderStartDate(DateUtils.dateToStamp(request.getSourceOrderBeginTime()));
        searchForecastOrderRequest.setSourceOrderEndDate(DateUtils.dateToStamp(request.getSourceOrderEndTime()));
        searchForecastOrderRequest.setDeliveryMethodCode(request.getDeliveryMethodCode());
        searchForecastOrderRequest.setAutoFulfillment(request.getAutoFulfillment());
        searchForecastOrderRequest.setGoodsCodeLike(request.getProductCode());
        searchForecastOrderRequest.setReceiveStatusList(request.getReceiveStatusList());

        Result<List<ForecastOrderSDO>> pageQueryByEsResult = null;
        try {
            pageQueryByEsResult = forecastOrderQueryRepository.pageQueryByEs(searchForecastOrderRequest);
        } catch (Exception e) {
            log.error("ForecastOrderBizQueryServiceImpl#pageQuery error", e);
            throw new FunctionException("OC-01-001-01-16-057", "查询预报订单失败");
        }
        if (Objects.isNull(pageQueryByEsResult) || CollectionUtils.isEmpty(pageQueryByEsResult.getResult())) {
            return Result.success(Lists.newArrayList());
        }

        List<DictionaryResponse> businessTypeResponseList = baseDataServiceAdapter.queryDictionarys(DictionaryTypeEnum.BUSINESS_TYPE.getCode());
        Map<String, DictionaryResponse> businessTypeMap = businessTypeResponseList.stream().collect(Collectors.toMap(DictionaryResponse::getCode, Function.identity(), (k1, k2) -> k2));
        List<QueryForecastResponse> responseList = pageQueryByEsResult.getResult().stream()
                .map(ForecastOrderSDOToResponseConvertor::convert)
                .collect(Collectors.toList());
        for (QueryForecastResponse queryForecastResponse : responseList) {
            queryForecastResponse.setBusinessTypeName("");
            if (queryForecastResponse.getBusinessType() != null && businessTypeMap.containsKey(queryForecastResponse.getBusinessType())) {
                queryForecastResponse.setBusinessTypeName(businessTypeMap.get(queryForecastResponse.getBusinessType()).getName());
            }
        }

        Result<List<QueryForecastResponse>> result = Result.success(responseList);
        result.setTotal(pageQueryByEsResult.getTotal());
        return result;
    }

    @Override
    public List<ForecastOrderSDO> pageQueryByEs(PageQueryForecastRequest request) {
        SearchForecastOrderRequest searchForecastOrderRequest = new SearchForecastOrderRequest();
        searchForecastOrderRequest.setForecastOrderBizNoList(request.getSalesOrderNoList());
        searchForecastOrderRequest.setSourceOrderNoList(request.getSourceOrderNoList());
        searchForecastOrderRequest.setFromSys(request.getFromSys());
        searchForecastOrderRequest.setBusinessType(request.getBusinessType());
        searchForecastOrderRequest.setBusinessUnitCode(request.getBusinessUnitCode());
        searchForecastOrderRequest.setShippingWarehouseCodeList(request.getShippingWarehouseCodeList());
        searchForecastOrderRequest.setOrderTypeCodeList(request.getOrderTypeCodeList());
        searchForecastOrderRequest.setDeliveryFactoryCode(request.getDeliveryFactoryCode());
        searchForecastOrderRequest.setStockCode(request.getStockCode());
        searchForecastOrderRequest.setPage(request.getPage() < 1 ? 1 : request.getPage());
        searchForecastOrderRequest.setSize(request.getSize());
        searchForecastOrderRequest.setLimit(request.getSize());
        searchForecastOrderRequest.setStart((searchForecastOrderRequest.getPage() - 1) * request.getSize());
        Result<List<ForecastOrderSDO>> pageQueryByEsResult = forecastOrderQueryRepository.pageQueryByEs(searchForecastOrderRequest);
        if (pageQueryByEsResult.isSuccess() && CollectionUtils.isEmpty(pageQueryByEsResult.getResult())) {
            return pageQueryByEsResult.getResult();
        }
        return new ArrayList<>();
    }

    @Override
    public Result<List<ForecastOrderBizQueryAnalysisResponse>> queryAnalysis(ForecastOrderBizQueryAnalysisRequest request) {
        log.info("ForecastOrderBizQueryServiceImpl#queryAnalysis request={}", request);

        List<Map> result = dealLineQueryRepository.listDealLineQueue(request.getBatchNo());
        log.info("ForecastOrderBizQueryServiceImpl#queryAnalysis queryProgressQueueResult result={}", result);
        if (CollectionUtils.isEmpty(result)) {
            return Result.success(Lists.newArrayList());
        }

        List<ForecastOrderBizQueryAnalysisResponse> responses = new ArrayList<>();
        result.forEach(map -> {
            String forecastOrderNo = Optional.ofNullable(map.get("forecastOrderNo")).orElse("").toString();
            String forecastOrderLineNum = Optional.ofNullable(map.get("forecastOrderLineNum")).orElse("").toString();
            boolean matchQuery = true;
            if (StringUtils.isBlank(forecastOrderLineNum)) {
                ForecastOrderLineSDO line = forecastOrderLineQueryRepository.query(map.get("forecastOrderLineId").toString());
                if (line != null) {
                    forecastOrderLineNum = line.getSerialNumber();
                    forecastOrderNo = line.getMainOrderBizId();
                }

                if (StringUtils.isNotBlank(forecastOrderNo)) {
                    ForecastOrderSDO order = forecastOrderQueryRepository.queryDetail(line.getMainOrderId());
                    if (order != null) {
                        forecastOrderNo = order.getOrderBizId();
                        if (StringUtils.isNotBlank(request.getBusinessType())) {
                            matchQuery = matchQuery && (request.getBusinessType().equals(order.getBusinessType()));
                        }
                        if (StringUtils.isNotBlank(request.getBusinessUnitCode())) {
                            matchQuery = matchQuery && (request.getBusinessUnitCode().equals(order.getBusinessUnitCode()));
                        }
                    }

                }
            }
            if (matchQuery) {
                responses.add(ForecastOrderBizQueryAnalysisResponse.builder()
                        .batchNo(map.get("batchNumber").toString())
                        .salesOrderNo(forecastOrderNo)
                        .lineNum(forecastOrderLineNum)
                        .dealStatus((int) Float.parseFloat(map.get("dealStatus").toString()))
                        .build());
            }
        });

        return Result.listSuccess(responses, responses.size());
    }

    @Override
    public List<ForecastOrderSDO> queryByOrderBizNo(List<String> bizOrderNos) {
        if (CollectionUtils.isEmpty(bizOrderNos)) {
            return Lists.newArrayList();
        }
        return forecastOrderQueryRepository.queryByOrderBizNo(bizOrderNos);
    }

    /**
     * 数据库预报单明细转QueryForecastDetailResponseDTO
     * 主单下的子单的转换
     */
    private QueryForecastDetailResponseDTO forecastOrderLine2QueryForecastDetailResponseDTO(ForecastOrderLine source) {
        QueryForecastDetailResponseDTO target = new QueryForecastDetailResponseDTO();
        target.setLineNum(nvlToEmptyStr(source.getSerialNumber()));
        target.setSourceLineNum(nvlToEmptyStr(source.getSourceLineNum()));
        target.setProductCode(nvlToEmptyStr(source.getScItemOutCode()));
        target.setProductName(nvlToEmptyStr(source.getScItemTitle()));
        target.setProductQuantity(nvlToEmptyStr(source.getQuantity()));
        target.setSalesUnitName(nvlToEmptyStr(source.getSaleUnit()));
        target.setSalesUnitCode(nvlToEmptyStr(source.getSaleUnitcode()));
        target.setStockUnitCode(nvlToEmptyStr(source.getInventoryUnitCode()));
        target.setStockUnitName(nvlToEmptyStr(source.getInventoryUnit()));
        target.setUnitConversionRelationship(nvlToEmptyStr(source.getUnitConvert()));
        target.setUnitPrice(MoneyUtils.moneyFen2Yuan(source.getUnitPrice()));
        target.setActivityPrice("");
        if (Objects.nonNull(source.getActivityPrice())) {
            target.setActivityPrice(MoneyUtils.moneyFen2Yuan(source.getActivityPrice()));
        }
        target.setNote(nvlToEmptyStr(source.getDetailRemark()));
        target.setActivityId(nvlToEmptyStr(source.getActivityCode()));
        //设置活动行号
        String activityNumber = "";
        String sourceUnit = "";
        String sourceQuantity = "";
        String sourcePrice = "";

        if (StringUtils.isNotBlank(source.getFeatures())) {
            Map<String, Object> features = JSON.parseObject(source.getFeatures(), Map.class);
            if (MapUtils.isNotEmpty(features)) {
                /* if (features.get("activityDteails") != null) {
                    String activityDetails = features.get("activityDteails").toString();
                    List<ActivitySDO> activitySDOS = JSONObject.parseArray(activityDetails, ActivitySDO.class);
                    if (CollectionUtils.isNotEmpty(activitySDOS)) {
                        List<String> collect = activitySDOS.stream().map(ActivitySDO::getActivityTermid).collect(Collectors.toList());
                        activityNumber = String.join("/", collect);
                    }
                } */

                if (StringUtils.isBlank(activityNumber) && Objects.nonNull(features.get("activityNumber"))) {
                    activityNumber = features.get("activityNumber").toString();
                }

                if (Objects.nonNull(features.get(OrderFeaturesKey.SOURCE_UNIT))) {
                    sourceUnit = String.valueOf(features.get(OrderFeaturesKey.SOURCE_UNIT));
                }
                if (Objects.nonNull(features.get(OrderFeaturesKey.SOURCE_PRICE))) {
                    sourcePrice = String.valueOf(features.get(OrderFeaturesKey.SOURCE_PRICE));
                }
                if (Objects.nonNull(features.get(OrderFeaturesKey.SOURCE_QUANTITY))) {
                    sourceQuantity = String.valueOf(features.get(OrderFeaturesKey.SOURCE_QUANTITY));
                }
            }
        }
        target.setActivityLineNo(activityNumber);
        target.setStatus(source.getStatus());
        target.setCloseCode(nvlToEmptyStr(source.getRefuseReasonCode()));
        target.setCloseMsg(nvlToEmptyStr(source.getRefuseReason()));
        target.setIsClose(ForecastStatusEnum.CANCELLED.getNumValue() == source.getStatus());
        target.setBizFeatures(nvlToEmptyStr(source.getBizFeatures()));
        //target.setStockCode(nvlToEmptyStr(source.getStockLocation()));
        target.setFactoryCode(nvlToEmptyStr(source.getFactoryCode()));
        target.setShippingWarehouseCode(nvlToEmptyStr(source.getShipWarehouseCode()));
        target.setShippingWarehouseName(nvlToEmptyStr(source.getShippingWarehouseName()));

        // 【产品编码】
        target.setInnerProductCode(nvlToEmptyStr(source.getInnerProductCode()));
        target.setInnerProductName(nvlToEmptyStr(source.getInnerProductName()));
        // 【产品条码】「目前不知道怎么来的」
        target.setBarCode(nvlToEmptyStr(source.getBarCode()));

        // 预计回复数量
        target.setPredictReplyAmount(source.getPredictReplyAmount());
        // 累计回复数量
        target.setActualTotalReplyAmount(source.getActualTotalReplyAmount());
        // 货品生产日期
        target.setProductionDate(nvlToEmptyStr(source.getGoodsProductationTime()));
        // 常规总金额
        target.setTotalAmount(MoneyUtils.moneyFen2Yuan(source.getTotalFee(), Boolean.FALSE));
        // 折扣后总金额
        target.setTotalActivityAmount(MoneyUtils.moneyFen2Yuan(source.getTotalActivityFee(), Boolean.FALSE));
        target.setOuterLineId(nvlToEmptyStr(source.getOuterLineId()));
        target.setSourceUnit(nvlToEmptyStr(sourceUnit));
        target.setSourceQuantity(nvlToEmptyStr(sourceQuantity));
        target.setSourcePrice(nvlToEmptyStr(sourcePrice));
        //target.setCreatorCode(source.getCreatorCode());
        //target.setCreatorName(source.getCreatorName());
        //target.setCreateTime(DateUtils.toDateStr(source.getGmt_create(), DATETIME_FORMAT));
        //target.setModifierCode(nvlToEmptyStr(source.getModifierCode()));
        //target.setModifierName(nvlToEmptyStr(source.getModifierName()));
        //target.setModifierTime(nvlToEmptyStr(DateUtils.toDateStr(source.getGmt_modified(), DATETIME_FORMAT)));
        //target.setActivityCode(nvlToEmptyStr(source.getActivityCode()));
        //target.setActivityName(nvlToEmptyStr(source.getActivityName()));
        target.setFactoryName("");
        target.setStockLocationName("");
        target.setStockLocation(nvlToEmptyStr(source.getStockLocation()));
        return target;
    }

    /**
     * 主单的对象转换
     */
    private QueryForecastResponse forecastOrder2QueryQueryForecastResponse(ForecastOrder source) {
        QueryForecastResponse queryForecastResponse = new QueryForecastResponse();
        queryForecastResponse.setSourceOrderNo(nvlToEmptyStr(source.getSourceOrderNo()));
        queryForecastResponse.setSalesOrderType(nvlToEmptyStr(source.getOrderTypeCode()));
        ForecastOrderTypeEnum forecastOrderTypeEnum = ForecastOrderTypeEnum.of(source.getOrderTypeCode());
        queryForecastResponse.setSalesOrderTypeName(Objects.isNull(forecastOrderTypeEnum) ? "" : forecastOrderTypeEnum.getDesc());
        queryForecastResponse.setSalesOrderNo(nvlToEmptyStr(source.getOrderBizId()));
        queryForecastResponse.setDeliveryMethodCode(nvlToEmptyStr(source.getTransportModeCode()));
        queryForecastResponse.setDeliveryMethodName(nvlToEmptyStr(source.getTransportModeName()));
        queryForecastResponse.setExpectedDeliveryDate(formatDate(source.getCustomerExpectTDate(), DateUtils.DATE_FORMAT));
        queryForecastResponse.setShipToPartyCode(nvlToEmptyStr(source.getShipToPartyCode()));
        queryForecastResponse.setShipToPartyName(nvlToEmptyStr(source.getShipToPartyName()));
        queryForecastResponse.setCustomerCode(nvlToEmptyStr(source.getCustomerCode()));
        queryForecastResponse.setCustomerName(nvlToEmptyStr(source.getCustomerName()));
        queryForecastResponse.setProductGroupCode(nvlToEmptyStr(source.getProductGroupCode()));
        queryForecastResponse.setProductGroupName(nvlToEmptyStr(source.getProductGroupName()));
        queryForecastResponse.setBusinessChannel(nvlToEmptyStr(source.getChannelCode()));
        queryForecastResponse.setBusinessChannelName(nvlToEmptyStr(source.getChannelName()));
        queryForecastResponse.setOrderReasonCode(nvlToEmptyStr(source.getCreateReasonCode()));
        queryForecastResponse.setOrderReasonName(nvlToEmptyStr(source.getCreateReasonName()));
        queryForecastResponse.setShippingWarehouseCode(nvlToEmptyStr(source.getShippingWarehouseCode()));
        queryForecastResponse.setShippingWarehouseName(nvlToEmptyStr(source.getShippingWarehouseName()));
        //queryForecastResponse.setDeliveryFactoryCode(nvlToEmptyStr(source.getDeliveryFactoryCode()));
        //queryForecastResponse.setStockCode(nvlToEmptyStr(source.getStockCode()));
        queryForecastResponse.setCustomerPurchaseOrderNo(nvlToEmptyStr(source.getCustomerPurchaseOrderNo()));
        queryForecastResponse.setCustomerPurchaseDate(formatDate(source.getCustomerPurchaseDate(), DateUtils.DATE_FORMAT));
        queryForecastResponse.setNote(nvlToEmptyStr(source.getRemark()));
        queryForecastResponse.setSalesOrganizationCode(nvlToEmptyStr(source.getSalesOrganizationCode()));
        queryForecastResponse.setSalesOrganizationName(nvlToEmptyStr(source.getSalesOrganizationName()));
        queryForecastResponse.setCreatorCode(nvlToEmptyStr(source.getCreatorCode()));
        queryForecastResponse.setCreatorName(nvlToEmptyStr(source.getCreatorName()));
        queryForecastResponse.setCreateTime(formatDate(source.getGmtCreate(), DateUtils.DATETIME_FORMAT));
        queryForecastResponse.setModifierCode(nvlToEmptyStr(source.getModifierCode()));
        queryForecastResponse.setModifierName(nvlToEmptyStr(source.getModifierName()));
        queryForecastResponse.setModifierTime(formatDate(source.getGmtModified(), DateUtils.DATETIME_FORMAT));
        queryForecastResponse.setBusinessType(nvlToEmptyStr(source.getBusinessType()));
        queryForecastResponse.setBusinessTypeName(nvlToEmptyStr(source.getBusinessTypeName()));
        queryForecastResponse.setFromSys(nvlToEmptyStr(source.getFromSys()));
        queryForecastResponse.setBusinessUnitCode(nvlToEmptyStr(source.getBusinessUnitCode()));
        queryForecastResponse.setBusinessUnitName(nvlToEmptyStr(source.getBusinessUnitName()));
        queryForecastResponse.setOrderStatus(source.getStatus());
        queryForecastResponse.setBizFeatures(nvlToEmptyStr(source.getBizFeatures()));
        queryForecastResponse.setVaildBeginDate(nvlToEmptyStr(formatDate(source.getVaildBeginTime(), DateUtils.DATE_FORMAT)));
        //queryForecastResponse.setReceiveStockCode(nvlToEmptyStr(source.getReceiveStockCode()));
        // 收货库存地点名称meiyou
        // queryForecastResponse.setReceiveStockName(source.getReceiveStockName());
        // 100 优先履约 为空时默认为不优先
        queryForecastResponse.setFulfillmentPriority(nvlToEmptyStr(source.getFulfillmentPriority()));
        if (StringUtils.isNotEmpty(source.getOrderTag())) {
            queryForecastResponse.setOrderBizTag(Arrays.asList(source.getOrderTag().split(",")));
        }
        //queryForecastResponse.setOrderTag(nvlToEmptyStr(source.getOrderTag()));
        queryForecastResponse.setOrderCategoryCode(nvlToEmptyStr(nvlToEmptyStr(source.getOrderCategoryCode())));
        //queryForecastResponse.setOrderCategoryName(OrderCategoryEnum.descByCode(source.getOrderCategoryCode()));
        queryForecastResponse.setOrderChannelCode(nvlToEmptyStr(source.getOrderChannelCode()));
        //queryForecastResponse.setOrderChannelName(OrderChannelEnum.descByCode(source.getOrderChannelCode()));
        queryForecastResponse.setOuterOrderCode(nvlToEmptyStr(source.getOuterOrderId()));
        queryForecastResponse.setFulfillmentTypeCode(nvlToEmptyStr(source.getFulfillmentTypeCode()));
        queryForecastResponse.setAutoFulfillment(nvlToEmptyStr(source.getAutoFulfillment()));
        queryForecastResponse.setCustomerGrade(nvlToEmptyStr(source.getCustomerGrade()));
        queryForecastResponse.setCustomerGroup(nvlToEmptyStr(source.getCustomerGroup()));
        queryForecastResponse.setCustomerGroupName(nvlToEmptyStr(source.getCustomerGroupName()));
        queryForecastResponse.setOuterOrderCode(nvlToEmptyStr(source.getOuterOrderId()));
        queryForecastResponse.setSalesChannelCode(nvlToEmptyStr(source.getSalesChannelCode()));
        queryForecastResponse.setSalesChannelName(nvlToEmptyStr(source.getSalesChannelName()));
        queryForecastResponse.setSalesDepartmentCode(nvlToEmptyStr(source.getSalesDepartmentCode()));
        queryForecastResponse.setSalesDepartmentName(nvlToEmptyStr(source.getSalesDepartmentName()));
        //queryForecastResponse.setReceiveWarehouseCode(nvlToEmptyStr(source.getReceiveWarehouseCode()));
        //queryForecastResponse.setReceiveWarehouseName(nvlToEmptyStr(source.getReceiveWarehouseName()));
        //queryForecastResponse.setReceiveFactoryCode(nvlToEmptyStr(source.getReceiveFactoryCode()));

        String kaSystem = "";
        String kaArea = "";
        String sourceOrderDate = "";
        if (StringUtils.isNotBlank(source.getFeatures())) {
            Map<String, Object> features = JSON.parseObject(source.getFeatures(), Map.class);
            if (MapUtils.isNotEmpty(features)) {
                if (Objects.nonNull(features.get(OrderFeaturesKey.KA_SYSTEM))) {
                    kaSystem = (String) features.get(OrderFeaturesKey.KA_SYSTEM);
                }
                if (Objects.nonNull(features.get(OrderFeaturesKey.KA_AREA))) {
                    kaArea = (String) features.get(OrderFeaturesKey.KA_AREA);
                }
                if (Objects.nonNull(features.get(OrderFeaturesKey.SOURCE_ORDER_DATE))) {
                    String sourceOrderDateStr = (String) features.get(OrderFeaturesKey.SOURCE_ORDER_DATE);
                    sourceOrderDate = DateUtils.stampToDate(sourceOrderDateStr);
                }
            }
        }
        queryForecastResponse.setKaSystem(kaSystem);
        queryForecastResponse.setKaArea(kaArea);
        queryForecastResponse.setSourceOrderTime(sourceOrderDate);
//        queryForecastResponse.setFactoryName("");
//        queryForecastResponse.setStockLocationName("");
//        queryForecastResponse.setStockLocation(nvlToEmptyStr(source.getStockCode()));

        return queryForecastResponse;
    }

    /**
     * 纯子单的对象转换
     */
    private PageQueryForecastDetailResponse forecastOrderLine2QueryQueryForecastResponse(ForecastOrderLineIndex source) {
        PageQueryForecastDetailResponse target = new PageQueryForecastDetailResponse();
        target.setSourceOrderNo(nvlToEmptyStr(source.getMainSourceOrderNo())); // 来源单号
        target.setOrderType(source.getMainOrderTypeCode()); // 订单类别编码
        target.setOrderTypeName(nvlToEmptyStr(source.getMainOrderTypeName())); // 订单类别名称
        if (StringUtils.isNotBlank(source.getMainOrderTypeCode()) && SaleOrderTag.of(source.getMainOrderTypeCode()) != null) {
            target.setOrderTypeName(SaleOrderTag.of(source.getMainOrderTypeCode()).getDesc()); // 订单类别名称
        }
        target.setSalesOrderNo(nvlToEmptyStr(source.getMainOrderBizId())); // 预报订单单号
        target.setExpectDeliveryDate(formatDate(new Date(source.getMainCustomerExpectTDate()), DateUtils.DATE_FORMAT)); // 期望交货日期
        target.setProductCode(nvlToEmptyStr(source.getSubScItemOutCode())); // 物料编码
        target.setProductName(nvlToEmptyStr(source.getSubScItemTitle())); // 物料名称
        target.setQuantity(nvlToEmptyStr(source.getSubQuantity())); // 预报数量
        target.setSalesUnitCode(nvlToEmptyStr(source.getSubSaleUnitcode())); // 销售单位编码
        target.setSalesUnitName(nvlToEmptyStr(source.getSubSaleUnit())); // 销售单位名称
        target.setStockUnitCode(nvlToEmptyStr(source.getSubInventoryUnitCode())); // 库存单位编码
        target.setStockUnitName(nvlToEmptyStr(source.getSubInventoryUnit())); // 库存单位名称
        target.setUnitConversionRelationship(nvlToEmptyStr(source.getSubUnitConvert())); // 单位转换关系
        target.setUnitPrice(MoneyUtils.moneyFen2Yuan(source.getSubUnitPrice())); // 常规单价
        // 折扣后单价
        target.setActivityPrice(Objects.isNull(source.getSubActivityPrice()) ? "" : MoneyUtils.moneyFen2Yuan(source.getSubActivityPrice()));
        target.setShipToPartyCode(nvlToEmptyStr(source.getMainShipToPartyCode())); // 客户送达方编码
        target.setShipToPartyName(nvlToEmptyStr(source.getMainShipToPartyName())); // 客户送达方名称
//        target.setReceiveAddressCode(source.getMainShipToPartyCode()); // 客户送达方编码
//        target.setReceiveAddressName(source.getMainShipToPartyName()); // 客户送达方名称
        target.setCustomerCode(nvlToEmptyStr(source.getMainCustomerCode())); // 客户售达方编码
        target.setCustomerName(nvlToEmptyStr(source.getMainCustomerName())); // 客户售达方名称
//        target.setCustomerCode(nvlToEmptyStr(source.getMainSoldToPartyCode())); // 客户售达方编码
//        target.setCustomerName(nvlToEmptyStr(source.getMainSoldToPartyName())); // 客户售达方名称

        target.setCloseCode(nvlToEmptyStr(source.getSubRefuseReasonCode()));
        target.setCloseMsg(nvlToEmptyStr(source.getSubRefuseReason()));
        if (source.getSubAnalysisTime() != null) {
            target.setAnalysisTime(formatDate(new Date(source.getSubAnalysisTime()), DateUtils.DATETIME_FORMAT));
        }
        target.setAnalysisReason(nvlToEmptyStr(source.getSubAnalysisReason()));
//        target.setActivityName(nvlToEmptyStr(source.getSubActivityName()));
//        target.setActivityCode(nvlToEmptyStr(source.getSubActivityCode()));
//        target.setActivityProjectCode(nvlToEmptyStr(source.getSubActivityNumber()));
        target.setActivityConfilctFlag(source.getSubActivityTag() != null && source.getSubActivityTag() > 0);
        Object giftObj = source.getSubGiftList();
        if (giftObj != null) {
            String giftJson = JSON.toJSONString(giftObj);
            List<ActivitySDO> activitySDOList = JSON.parseArray(giftJson, ActivitySDO.class);
            List<String> giftGoodsCodeList = new ArrayList<>();
            List<String> giftGoodsNameList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(activitySDOList)) {
                for (ActivitySDO x : activitySDOList) {
                    x.getGiftList().stream().forEach(y -> {
                        giftGoodsCodeList.add(y.getScItemCode());
                        giftGoodsNameList.add(y.getGiftName());
                    });
                }
            }
            target.setGiftGoodsCode(giftGoodsCodeList);
            target.setGiftGoodsName(giftGoodsNameList);
        }
        target.setShippingWarehouseCode(nvlToEmptyStr(source.getSubShipWarehouseCode())); // 子单发货仓编码
        target.setShippingWarehouseName(nvlToEmptyStr(source.getSubShippingWarehouseName())); // 子单发货仓名称
//        target.setNeedReplyAmount(String.valueOf(null == source.getMainTotalReplyAmount() ? 0 : source.getMainTotalReplyAmount()));
        Long actualTotalReplyAmount = null == source.getSubActualTotalReplyAmount() ? 0 : source.getSubActualTotalReplyAmount();
        Long quantity = StringUtils.isBlank(source.getSubQuantity()) ? 0 : Long.valueOf(source.getSubQuantity());
        Long needReplyAmount = quantity - actualTotalReplyAmount;
        target.setNeedReplyAmount(String.valueOf(needReplyAmount));
        target.setHitActivityFlag(source.getSubActivityTag() != null && source.getSubActivityTag() > 0);
//        target.setActualTotalReplyAmount(MoneyUtils.moneyFen2Yuan(source.getSubActualTotalReplyAmount())); // 累计回复数量
        target.setActualTotalReplyAmount(String.valueOf(null == source.getSubActualTotalReplyAmount() ? 0 : source.getSubActualTotalReplyAmount())); // 累计回复数量
        target.setPredictReplyAmount(String.valueOf(null == source.getSubPredictReplyAmount() ? 0 : source.getSubPredictReplyAmount())); // 预计回复数量
//        target.setDealStatus(String.valueOf(source.getSubDealStatus()));
        target.setDeliveryFactoryCode(nvlToEmptyStr(source.getMainDeliveryFactoryCode())); // 发货工厂编码
        target.setStockCode(nvlToEmptyStr(source.getMainStockCode())); // 发货库存地点编码
        target.setDetailNote(nvlToEmptyStr(source.getSubDetailRemark())); // 订单行备注
        target.setNote(nvlToEmptyStr(source.getMainRemark())); // 订单头备注
        target.setCreateTime(formatDate(new Date(source.getMainGmtCreate()), DateUtils.DATETIME_FORMAT)); // 创建时间
        target.setBusinessType(nvlToEmptyStr(source.getMainBusinessType())); // 业态编码
        target.setBusinessTypeName(nvlToEmptyStr(source.getMainBusinessTypeName())); // 业态名称
        target.setFromSys(nvlToEmptyStr(source.getMainFromSys())); // 来源系统编码
        target.setBusinessUnitCode(nvlToEmptyStr(source.getMainBusinessUnitCode())); // 业务单元编码
        target.setBusinessUnitName(nvlToEmptyStr(source.getMainBusinessUnitName())); // 业务单元名称
        target.setLineNum(nvlToEmptyStr(source.getSubSerialNumber())); // 预报单行号
        target.setStatus(String.valueOf(source.getMainStatus())); // 主单状态

        // 一盘货新增出参
        target.setOrderCategoryCode(nvlToEmptyStr(nvlToEmptyStr(source.getMainOrderCategoryCode())));
        target.setOrderCategoryName(OrderCategoryEnum.descByCode(source.getMainOrderCategoryCode()));
        target.setOrderChannelCode(nvlToEmptyStr(source.getMainOrderChannelCode())); // 订单渠道编码
        if (StringUtils.isNotBlank(source.getMainOrderChannelCode())) {
            target.setOrderChannelName(OrderChannelEnum.descByCode(source.getMainOrderChannelCode())); // 订单渠道名称
        } else {
            target.setOrderChannelName("");
        }
        target.setOutOrderNo(nvlToEmptyStr(source.getMainOuterOrderId())); // 外部单号
        target.setProductGroupCode(nvlToEmptyStr(source.getMainProductGroupCode())); // 产品组编码
        target.setProductGroupName(nvlToEmptyStr(source.getMainProductGroupName())); // 产品组名称
        target.setBusinessChannel(nvlToEmptyStr(source.getMainChannelCode())); // 业务渠道编码
        target.setBusinessChannelName(nvlToEmptyStr(source.getMainChannelName())); // 业务渠道名称
        target.setSalesOrganizationCode(nvlToEmptyStr(source.getMainSalesOrganizationCode())); // 销售组织编码
        target.setSalesOrganizationName(nvlToEmptyStr(source.getMainSalesOrganizationName())); // 销售组织名称
        target.setSalesDepartmentCode(nvlToEmptyStr(source.getMainSalesDepartmentCode())); // 销售部门编码
        target.setSalesDepartmentName(nvlToEmptyStr(source.getMainSalesDepartmentName())); // 销售部门名称
        target.setSalesChannelCode(nvlToEmptyStr(source.getMainSaleChannelCode())); // 销售组编码
        target.setSalesChannelName(nvlToEmptyStr(source.getMainSaleChannelName())); // 销售组名称
        target.setCustomerGrade(nvlToEmptyStr(source.getMainCustomerGrade())); // 客户等级
        target.setCustomerGroup(nvlToEmptyStr(source.getMainCustomerGroup())); // 客户组
        target.setCustomerGroupName(nvlToEmptyStr(source.getMainCustomerGroupName())); // 客户组名称
        target.setDeliveryMethodCode(nvlToEmptyStr(source.getMainTransportModeCode())); // 配送方式编码
        target.setDeliveryMethodName(nvlToEmptyStr(source.getMainTransportModeName())); // 配送方式名称
        target.setValidBeginDate(formatDate(new Date(source.getMainVaildBeginTime()))); // 生效开始日期
        target.setFulfillmentTypeCode(nvlToEmptyStr(source.getMainFulfillmentTypeCode())); // 履约方式
        target.setFulfillmentPriority(nvlToEmptyStr(source.getMainFulfillmentPriority())); // 履约优先级
        target.setAutoFulfillment(nvlToEmptyStr(source.getMainAutoFulfillment())); // 是否自动创建履约单
        target.setOrderBizTag(Lists.newArrayList(StringUtils.split(nvlToEmptyStr(source.getMainOrderTag()), ','))); // 订单标签list
        target.setOrderReasonCode(nvlToEmptyStr(source.getMainCreateReason())); // 订单原因编码
        target.setOrderReasonName(nvlToEmptyStr(source.getMainCreateReasonName())); // 订单原因名称
        target.setCreatorCode(nvlToEmptyStr(source.getMainCreatorCode())); // 创建人工号
        target.setCreatorName(nvlToEmptyStr(source.getMainCreatorName())); // 创建人姓名
        target.setModifierCode(nvlToEmptyStr(source.getMainModifierCode())); // 修改人工号
        target.setModifierName(nvlToEmptyStr(source.getMainModifierName())); // 修改人姓名
        target.setModifiedTime(formatDate(new Date(source.getMainGmtModified()), DateUtils.DATETIME_FORMAT)); // 修改时间
        target.setCustomerPurchaseOrderNo(nvlToEmptyStr(source.getMainCustomerPurchaseOrderNo())); // 客户采购订单号
        if (Objects.nonNull(source.getMainCustomerPurchaseDate())) {
            target.setCustomerPurchaseDate(formatDate(new Date(source.getMainCustomerPurchaseDate()))); // 客户采购订单日期
        } else {
            target.setCustomerPurchaseDate("");
        }
        target.setBizFeatures(nvlToEmptyStr(source.getMainBizFeatures())); // 扩展字段（主单）
        target.setSourceLineNum(nvlToEmptyStr(source.getSubSourceLineNum())); // 预报单行号
        target.setOutLineNum(nvlToEmptyStr(source.getSubOuterLineId())); // 外部单行号
        target.setInnerProductCode(nvlToEmptyStr(source.getSubInnerProductCode())); // 产品编码
        target.setInnerProductName(nvlToEmptyStr(source.getSubInnerProductName())); // 产品名称
        target.setProductBarCode(nvlToEmptyStr(source.getSubBarCode())); // 产品名称
        target.setTotalAmount(String.valueOf(source.getSubTotalFee())); // 常规总金额
        target.setActivityTotalAmount(Objects.isNull(source.getSubTotalActivityFee()) ? "" : String.valueOf(source.getSubTotalActivityFee())); // 折扣后总金额
        target.setProductionDate(nvlToEmptyStr(source.getSubGoodsProductationTime())); // 生产日期
        target.setIsClose(String.valueOf(Long.valueOf(0).equals(source.getSubClosed()))); // 是否关闭
        target.setCloseCode(nvlToEmptyStr(source.getSubRefuseReasonCode())); // 关闭原因编码
        target.setCloseMsg(nvlToEmptyStr(source.getSubRefuseReason())); // 关闭原因名称
        target.setDetailStatus(nvlToEmptyStr(String.valueOf(source.getSubStatus()))); // 子单状态
        target.setDetailBizFeatures(nvlToEmptyStr(source.getSubBizFeatures())); // 扩展字段（子单）
        target.setReceiveWarehouseCode(nvlToEmptyStr(source.getMainReceiveWarehouseCode())); // 收货仓编码
        target.setReceiveWarehouseName(nvlToEmptyStr(source.getMainReceiveWarehouseName())); // 收货仓名称
        target.setReceiveFactoryCode(nvlToEmptyStr(source.getMainReceiveFactoryCode())); // 收货工厂编码
        target.setReceiveStockCode(nvlToEmptyStr(source.getMainReceiveStockCode())); // 收货库存地点编码
        target.setSourceUnit(source.getSubSourceUnit());
        target.setSourceQuantity(source.getSubSourceQuantity());
        target.setSourcePrice(Objects.isNull(source.getSubSourcePrice()) ? "" : source.getSubSourcePrice());
        String kaSystem = "";
        String kaArea = "";
        String sourceOrderDate = "";
        if (StringUtils.isNotBlank(source.getMainFeatures())) {
            Map<String, Object> features = JSON.parseObject(source.getMainFeatures(), Map.class);
            if (MapUtils.isNotEmpty(features)) {
                if (Objects.nonNull(features.get(OrderFeaturesKey.KA_SYSTEM))) {
                    kaSystem = (String) features.get(OrderFeaturesKey.KA_SYSTEM);
                }
                if (Objects.nonNull(features.get(OrderFeaturesKey.KA_AREA))) {
                    kaArea = (String) features.get(OrderFeaturesKey.KA_AREA);
                }
                if (Objects.nonNull(features.get(OrderFeaturesKey.SOURCE_ORDER_DATE))) {
                    sourceOrderDate = DateUtils.stampToDate((String) features.get(OrderFeaturesKey.SOURCE_ORDER_DATE));
                }
            }
        }
        target.setKaSystem(kaSystem);
        target.setKaArea(kaArea);
        target.setSourceOrderTime(sourceOrderDate);
        target.setDealStatus(String.valueOf(source.getSubDealStatus()));
        target.setDeadline(StringUtils.isNotBlank(source.getSubDeadline()) ? formatDate(new Date(Long.parseLong(source.getSubDeadline())), DateUtils.DATETIME_FORMAT) : "");
        return target;
    }

    /**
     * 字段值如果为空，返回空字符串，而不是null。
     *
     * @param source
     * @return
     */
    private String nvlToEmptyStr(String source) {
        if (StringUtils.isBlank(source)) {
            return "";
        }
        return source;
    }
}
